package com.xcdh.base.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlLike;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xcdh.base.service.RoleMenuService;
import com.xcdh.base.service.UserRoleService;
import com.xcdh.commons.utils.UserContext;
import com.xcdh.domain.RequestPage;
import com.xcdh.domain.entity.MenuDO;
import com.xcdh.base.mapper.MenuMapper;
import com.xcdh.base.service.MenuService;
import com.xcdh.domain.entity.RoleMenuDO;
import com.xcdh.domain.entity.UserRoleDO;
import com.xcdh.domain.vo.ElTree;
import com.xcdh.domain.vo.MenuTreeVo;
import com.xcdh.domain.vo.TypeValueA2B;
import com.xcdh.domain.vo.UserVo;
import com.xcdh.util.TreeUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, MenuDO> implements MenuService {
    @Autowired
    private UserRoleService userRoleService ;
    @Autowired
    private RoleMenuService roleMenuService ;

    @Override
    public IPage<MenuDO> list(RequestPage<MenuDO> query) {
        UserVo user = UserContext.getUser();
        MenuDO model = query.getModel();
        QueryWrapper<MenuDO> queryWrapper = new QueryWrapper<>() ;
        LambdaQueryWrapper<MenuDO> menuDOLambdaQueryWrapper = queryWrapper.lambda().eq(MenuDO::getParentId, -1)
                .like(StringUtils.isNotBlank(model.getName()), MenuDO::getName, model.getName())
                .orderByDesc(MenuDO::getSortOrder);
        if(user.isAdmin()){
            RequestPage<MenuDO> page = super.page(query, queryWrapper);
            setChildren(page.getRecords()) ;
            return page ;
        }
        List<UserRoleDO> list = userRoleService.lambdaQuery().eq(UserRoleDO::getUserId, user.getUserId()).list();
        List<RoleMenuDO> rms = roleMenuService.lambdaQuery()
                .in(RoleMenuDO::getRoleId, list.stream().map(UserRoleDO::getRoleId).collect(Collectors.toList())).list();
        menuDOLambdaQueryWrapper
                .in(MenuDO::getMenuId , rms.stream().map(RoleMenuDO::getMenuId).collect(Collectors.toList())) ;
        RequestPage<MenuDO> page = super.page(query, queryWrapper);
        setChildren(page.getRecords()) ;
        return page ;
    }

    @Override
    public List<MenuDO> asideMenuTree(MenuDO menuDO) {
        UserVo user = UserContext.getUser();
        QueryWrapper<MenuDO> queryWrapper = new QueryWrapper<>() ;
        LambdaQueryWrapper<MenuDO> menuDOLambdaQueryWrapper = queryWrapper.lambda().eq(MenuDO::getParentId, -1)
                .orderByDesc(MenuDO::getSortOrder);
        if(user.isAdmin()){
            List<MenuDO> menuDOS = list(menuDOLambdaQueryWrapper);
            setMenuChildren(menuDOS);
            return  menuDOS;
        }
        List<UserRoleDO> list = userRoleService.lambdaQuery().eq(UserRoleDO::getUserId, user.getUserId()).list();
        List<RoleMenuDO> rms = roleMenuService.lambdaQuery()
                .in(RoleMenuDO::getRoleId, list.stream().map(UserRoleDO::getRoleId).collect(Collectors.toList())).list();
        menuDOLambdaQueryWrapper
                .in(MenuDO::getMenuId , rms.stream().map(RoleMenuDO::getMenuId).collect(Collectors.toList())) ;
        List<MenuDO> menuDOS = list(menuDOLambdaQueryWrapper);
        setMenuChildren(menuDOS) ;
        return menuDOS ;
    }

    @Override
    public List<ElTree> listElTree(MenuDO menuDO) {
        UserVo user = UserContext.getUser();
        if(user.isAdmin()){
            List<MenuDO> menuDOS = lambdaQuery().orderByDesc(MenuDO::getSortOrder).list();
        }

        return null;
    }

    private List<ElTree<Long>> elTreeList(List<MenuDO> menuDOS){
        List<MenuTreeVo> menuTreeVos = menuDOS.stream().map(menu -> {
            MenuTreeVo menuTreeVo = TypeValueA2B.a2b(menu, MenuTreeVo.class);
            menuTreeVo.setId(menu.getMenuId());
            menuTreeVo.setParentId(menu.getParentId());
            return menuTreeVo ;
        }).collect(Collectors.toList());
        return  TreeUtil.buildTree(menuTreeVos);
    }
    private void setChildren(List<MenuDO> menuDO){
        for (MenuDO aDo : menuDO) {
            List<MenuDO> list = lambdaQuery()
                    .eq(MenuDO::getParentId, aDo.getMenuId())
                    .list();
            setChildren(list) ;
            aDo.setChildren(list);
        }
    }

    private void setMenuChildren(List<MenuDO> menuDO){
        for (MenuDO aDo : menuDO) {
            List<MenuDO> list = lambdaQuery()
                    .eq(MenuDO::getParentId, aDo.getMenuId())
                    .eq(MenuDO::getType,"0")
                    .list();
            setMenuChildren(list) ;
            aDo.setChildren(list);
        }
    }
}
